<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>对象继承</title>
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-base.css" />
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-medium.css" />

 </head>
 <body class="docs"><div class="navbar navbar-fixed-top">
  <div class="navbar-inner clearfix">
    <ul class="nav" style="width: 100%">
      <li style="float: left;"><a href="language.oop5.visibility.html">« 访问控制（可见性）</a></li>
      <li style="float: right;"><a href="language.oop5.paamayim-nekudotayim.html">范围解析操作符 （::） »</a></li>
    </ul>
  </div>
</div>
<div id="breadcrumbs" class="clearfix">
  <ul class="breadcrumbs-container">
    <li><a href="index.html">PHP Manual</a></li>
    <li><a href="language.oop5.html">类与对象</a></li>
    <li>对象继承</li>
  </ul>
</div>
<div id="layout">
  <div id="layout-content"><div id="language.oop5.inheritance" class="sect1">
 <h2 class="title">对象继承</h2>
 <p class="para">
  继承已为大家所熟知的一个程序设计特性，PHP 的对象模型也使用了继承。继承将会影响到类与类，对象与对象之间的关系。
 </p>
 <p class="para">
  比如，当扩展一个类，子类就会继承父类所有 public 和 protected 的方法，属性和常量。除非子类覆盖了父类的方法，被继承的方法都会保留其原有功能。
 </p>
 <p class="para">
  继承有助于功能的设计和抽象，在实现类似的对象、增加新功能时，无须重复编写这些公用的功能。
 </p>
  <p class="para">
   子类无法访问父类的私有方法。因此，子类无需考虑正常的继承规则而重新实现私有方法。
   然而，在 PHP 8.0.0 之前， <code class="literal">final</code> 和 <code class="literal">static</code>
   的限制会应用于 private 方法。
   从 PHP 8.0.0 开始，仅 <code class="literal">private final</code> 的构造器是唯一受限的 private 方法；
   想要“禁用”构造器，我们通常用静态工厂方法作为代替。
  </p>
 <p class="para">
  方法，属性和常量的 <a href="language.oop5.visibility.html" class="link">可见性</a>
  可以放宽，例如 <code class="literal">protected</code> 方法可以标记为 <code class="literal">public</code>，
  但不能增加限制，例如标记 <code class="literal">public</code> 属性为 <code class="literal">private</code>。
 </p>

 <blockquote class="note"><p><strong class="note">注意</strong>: 
  <p class="para">
   除非使用了自动加载，否则一个类必须在使用之前被定义。如果一个类扩展了另一个，则父类必须在子类之前被声明。此规则适用于类继承其它类与接口。
  </p>
 </p></blockquote>
 <blockquote class="note"><p><strong class="note">注意</strong>: 
  <p class="para">
   It is not allowed to override a read-write property with a <a href="language.oop5.properties.html#language.oop5.properties.readonly-properties" class="link">readonly property</a> or vice versa.
   <div class="example" id="example-237">
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">A&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">int&nbsp;$prop</span><span style="color: #007700">;<br />}<br />class&nbsp;</span><span style="color: #0000BB">B&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">A&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;Illegal:&nbsp;read-write&nbsp;-&gt;&nbsp;readonly<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">readonly&nbsp;int&nbsp;$prop</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

   </div>
  </p>
 </p></blockquote>

 <div class="sect2" id="language.oop5.inheritance.examples">
  <div class="example" id="language.oop5.inheritance.examples.ex1">
   <p><strong>示例 #1 继承示例</strong></p>
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #0000BB">$string</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">'Foo:&nbsp;'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$string&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">printPHP</span><span style="color: #007700">()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">'PHP&nbsp;is&nbsp;great.'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />class&nbsp;</span><span style="color: #0000BB">Bar&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #0000BB">$string</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">'Bar:&nbsp;'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$string&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000BB">$foo&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$bar&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Bar</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$foo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #DD0000">'baz'</span><span style="color: #007700">);&nbsp;</span><span style="color: #FF8000">//&nbsp;输出:&nbsp;'Foo:&nbsp;baz'<br /></span><span style="color: #0000BB">$foo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printPHP</span><span style="color: #007700">();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;输出:&nbsp;'PHP&nbsp;is&nbsp;great'&nbsp;<br /></span><span style="color: #0000BB">$bar</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #DD0000">'baz'</span><span style="color: #007700">);&nbsp;</span><span style="color: #FF8000">//&nbsp;输出:&nbsp;'Bar:&nbsp;baz'<br /></span><span style="color: #0000BB">$bar</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printPHP</span><span style="color: #007700">();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;输出:&nbsp;'PHP&nbsp;is&nbsp;great'<br /><br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

  </div>
 </div>

 <div class="sect2" id="language.oop5.inheritance.internal-classes">
  <h3 class="title">Return Type Compatibility with Internal Classes</h3>

  <p class="para">
   Prior to PHP 8.1, most internal classes or methods didn&#039;t declare their return types,
   and any return type was allowed when extending them.
  </p>

  <p class="para">
   As of PHP 8.1.0, most internal methods started to &quot;tentatively&quot; declare their return type,
   in that case the return type of methods should be compatible with the parent being extended;
   otherwise, a deprecation notice is emitted.
   Note that lack of an explicit return declaration is also considered a signature mismatch,
   and thus results in the deprecation notice.
  </p>

  <p class="para">
   If the return type cannot be declared for an overriding method due to PHP cross-version compatibility concerns,
   a <code class="code">#[ReturnTypeWillChange]</code> attribute can be added to silence the deprecation notice.
  </p>

  <div class="example" id="example-239">
   <p><strong>示例 #2 The overriding method does not declare any return type</strong></p>
   <div class="example-contents">
    <div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">MyDateTime&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">DateTime<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">modify</span><span style="color: #007700">(</span><span style="color: #0000BB">string&nbsp;$modifier</span><span style="color: #007700">)&nbsp;{&nbsp;return&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">;&nbsp;}<br />}<br /><br /></span><span style="color: #FF8000">//&nbsp;"Deprecated:&nbsp;Return&nbsp;type&nbsp;of&nbsp;MyDateTime::modify(string&nbsp;$modifier)&nbsp;should&nbsp;either&nbsp;be&nbsp;compatible&nbsp;with&nbsp;DateTime::modify(string&nbsp;$modifier):&nbsp;DateTime|false,&nbsp;or&nbsp;the&nbsp;#[\ReturnTypeWillChange]&nbsp;attribute&nbsp;should&nbsp;be&nbsp;used&nbsp;to&nbsp;temporarily&nbsp;suppress&nbsp;the&nbsp;notice"&nbsp;as&nbsp;of&nbsp;PHP&nbsp;8.1.0<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

  </div>

  <div class="example" id="example-240">
   <p><strong>示例 #3 The overriding method declares a wrong return type</strong></p>
   <div class="example-contents">
    <div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">MyDateTime&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">DateTime<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">modify</span><span style="color: #007700">(</span><span style="color: #0000BB">string&nbsp;$modifier</span><span style="color: #007700">):&nbsp;?</span><span style="color: #0000BB">DateTime&nbsp;</span><span style="color: #007700">{&nbsp;return&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;&nbsp;}<br />}<br /><br /></span><span style="color: #FF8000">//&nbsp;"Deprecated:&nbsp;Return&nbsp;type&nbsp;of&nbsp;MyDateTime::modify(string&nbsp;$modifier):&nbsp;?DateTime&nbsp;should&nbsp;either&nbsp;be&nbsp;compatible&nbsp;with&nbsp;DateTime::modify(string&nbsp;$modifier):&nbsp;DateTime|false,&nbsp;or&nbsp;the&nbsp;#[\ReturnTypeWillChange]&nbsp;attribute&nbsp;should&nbsp;be&nbsp;used&nbsp;to&nbsp;temporarily&nbsp;suppress&nbsp;the&nbsp;notice"&nbsp;as&nbsp;of&nbsp;PHP&nbsp;8.1.0<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

  </div>

  <div class="example" id="example-241">
   <p><strong>示例 #4 The overriding method declares a wrong return type without a deprecation notice</strong></p>
   <div class="example-contents">
    <div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">MyDateTime&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">DateTime<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;DateTime|false<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;#[ReturnTypeWillChange]<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">modify</span><span style="color: #007700">(</span><span style="color: #0000BB">string&nbsp;$modifier</span><span style="color: #007700">)&nbsp;{&nbsp;return&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">;&nbsp;}<br />}<br /><br /></span><span style="color: #FF8000">//&nbsp;No&nbsp;notice&nbsp;is&nbsp;triggered<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

  </div>

 </div>

</div></div></div></body></html>